﻿// FileManagerDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "FileManager.h"
#include "FileManagerDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CFileManagerDlg 对话框

CFileManagerDlg::CFileManagerDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_FILEMANAGER_DIALOG, pParent) {
	//m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_hIcon = AfxGetApp()->LoadIcon(IDR_LOGO);
}

CListCtrl m_fileListCtrl;
std::vector<CFileInfo> m_curFolderFileInfo;
CStatic m_projectNum;
CImageList m_imageList;  // 图像列表
CFileManagerDlg::~CFileManagerDlg() {
	if (m_hThread) {
		TerminateThread(m_hThread, 0);
		CloseHandle(m_hThread);
		m_hThread = nullptr;
	}
}

void CFileManagerDlg::DoDataExchange(CDataExchange* pDX) {
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST, m_fileListCtrl);
	DDX_Control(pDX, IDC_EDIT_FILEPATH, m_filePathEdit);
	DDX_Control(pDX, IDC_STATIC_PROJECT_NUM, m_projectNum);
}

BEGIN_MESSAGE_MAP(CFileManagerDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_BACK, &CFileManagerDlg::OnBnClickedButtonBack)
	ON_BN_CLICKED(IDC_BUTTON_PARENT, &CFileManagerDlg::OnBnClickedButtonParent)
	ON_BN_CLICKED(IDC_BUTTON_FOLDER, &CFileManagerDlg::OnBnClickedButtonFolder)
	ON_NOTIFY(NM_DBLCLK, IDC_LIST, &CFileManagerDlg::OnNMDblclkList)
	ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST, &CFileManagerDlg::OnLvnColumnclickList)
END_MESSAGE_MAP()

BOOL CFileManagerDlg::OnInitDialog() {
	CDialogEx::OnInitDialog();
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	m_fileListCtrl.InsertColumn(0, L"名称", LVCFMT_LEFT, 300);
	m_fileListCtrl.InsertColumn(1, L"修改日期", LVCFMT_LEFT, 150);
	m_fileListCtrl.InsertColumn(2, L"类型", LVCFMT_LEFT, 190);
	m_fileListCtrl.InsertColumn(3, L"大小", LVCFMT_LEFT, 100);
	m_fileListCtrl.SetExtendedStyle(LVS_EX_GRIDLINES);

	// 初始化图像列表
	m_imageList.Create(16, 16, ILC_COLOR32, 2, 2);
	m_fileListCtrl.SetImageList(&m_imageList, LVSIL_SMALL);
	m_currentPath = _T("C:\\");
	m_filePathEdit.SetWindowText(m_currentPath);
	m_historyStack.push(m_currentPath);
	ShowFileList(m_currentPath);
	CString statusText = L"加载中";
	m_projectNum.SetWindowText(statusText);
	return TRUE;
}

BOOL CFileManagerDlg::PreTranslateMessage(MSG* pMsg) {
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
		if (GetFocus() == &m_filePathEdit) {
			OnEnReturnEditFilePath();
			return TRUE;
		}
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}

HICON GetFileIcon(LPCTSTR pszFilePath) {
	SHFILEINFO sfi;
	memset(&sfi, 0, sizeof(sfi));
	if (SHGetFileInfo(pszFilePath, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON)) {
		return sfi.hIcon;
	}
	return nullptr;
}

HICON GetFolderIcon(LPCTSTR pszFolderPath) {
	SHFILEINFO sfi;
	memset(&sfi, 0, sizeof(sfi));
	if (SHGetFileInfo(pszFolderPath, FILE_ATTRIBUTE_DIRECTORY, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_LARGEICON)) {
		return sfi.hIcon;
	}
	return nullptr;
}
CString GetFileType(LPCTSTR pszFilePath) {
	SHFILEINFO shfi;
	memset(&shfi, 0, sizeof(shfi));
	if (SHGetFileInfo(pszFilePath, 0, &shfi, sizeof(shfi), SHGFI_TYPENAME)) {
		return shfi.szTypeName;
	}
	return _T("未知文件类型");
}

void RetrieveFolderContents(const CString& path) {
	m_curFolderFileInfo.clear(); // 清空当前文件夹信息
	CFileFind finder;
	CString strWildcard(path);
	strWildcard += _T("\\*.*");
	BOOL bWorking = finder.FindFile(strWildcard);
	while (bWorking) {
		bWorking = finder.FindNextFile();
		if (finder.IsDots())
			continue;

		CFileInfo fileInfo;
		fileInfo.m_bIsDir = finder.IsDirectory();
		fileInfo.m_filePath = finder.GetFilePath();
		fileInfo.m_fileName = finder.GetFileName();
		GetFileType(fileInfo.m_filePath);
		CTime time;
		finder.GetLastWriteTime(time);
		fileInfo.m_fileModifyDate = time.Format(_T("%Y-%m-%d %H:%M:%S"));
		fileInfo.m_fileType = GetFileType(fileInfo.m_filePath);
		if (fileInfo.m_bIsDir) {
			fileInfo.m_fileSize = 0;
			HICON hIcon = GetFolderIcon(fileInfo.m_filePath);
			fileInfo.m_iconIndex = m_imageList.Add(hIcon);
			DestroyIcon(hIcon); // 销毁图标以避免内存泄漏
		}
		else {
			HICON hIcon = GetFileIcon(fileInfo.m_filePath);
			fileInfo.m_iconIndex = m_imageList.Add(hIcon);
			DestroyIcon(hIcon); // 销毁图标以避免内存泄漏
			ULONGLONG fileSize = finder.GetLength();
			fileInfo.m_fileSize = static_cast<UINT>((fileSize + 1023) / 1024); // KB为单位，不足1KB按1KB计算
		}

		m_curFolderFileInfo.push_back(fileInfo);
	}
	finder.Close();
}

void ShowFileListImpl() {
	// 处理数据的逻辑
	int fileNum = m_curFolderFileInfo.size();
	if (fileNum > 0) {
		for (int i = 0; i < fileNum; i++) {
			int iconIndex = m_curFolderFileInfo[i].m_iconIndex;
			m_fileListCtrl.InsertItem(LVIF_TEXT | LVIF_IMAGE, i, m_curFolderFileInfo[i].m_fileName, 0, 0, iconIndex, 0);
			m_fileListCtrl.SetItemText(i, 1, m_curFolderFileInfo[i].m_fileModifyDate);
			m_fileListCtrl.SetItemText(i, 2, m_curFolderFileInfo[i].m_fileType);
			if (!m_curFolderFileInfo[i].m_bIsDir) {
				CString fileSize;
				fileSize.Format(L"%dKB", m_curFolderFileInfo[i].m_fileSize);
				m_fileListCtrl.SetItemText(i, 3, fileSize);
			}
			m_fileListCtrl.SetItemData(i, i); // 设置lParam为当前文件项的索引
		}
	}
	CString statusText;
	statusText.Format(_T("项目总数: %d"), fileNum);
	m_projectNum.SetWindowText(statusText);
}

DWORD WINAPI ShowFileListThreadFunc(LPVOID pParam) {
	CString* pPath = reinterpret_cast<CString*>(pParam);
	CString path = *pPath;
	delete pPath;
	if (path != L"") {
		RetrieveFolderContents(path);
	}
	ShowFileListImpl();
	return 0;
}

void CFileManagerDlg::ShowFileList(const CString path = NULL) {
	// 停止之前的线程
	if (m_hThread) {
		TerminateThread(m_hThread, 0);
		CloseHandle(m_hThread);
		m_hThread = nullptr;
	}

	CString* pParm = new CString(path);
	m_hThread = CreateThread(nullptr, 0, ShowFileListThreadFunc, pParm, 0, nullptr);
}

void CFileManagerDlg::OnPaint() {
	if (IsIconic()) {
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else {
		CDialogEx::OnPaint();
	}
}

HCURSOR CFileManagerDlg::OnQueryDragIcon() {
	return static_cast<HCURSOR>(m_hIcon);
}

void CFileManagerDlg::OnEnReturnEditFilePath() {
	CString newPath;
	m_filePathEdit.GetWindowText(newPath);

	// 检查路径是否存在
	if (PathFileExists(newPath)) {
		// 路径合法且存在
		m_currentPath = newPath;
		m_fileListCtrl.DeleteAllItems();
		ShowFileList(m_currentPath);

		CString statusText = L"加载中";
		m_projectNum.SetWindowText(statusText);
		m_historyStack.push(m_currentPath);
	}
	else {
		// 路径不存在，显示错误消息
		MessageBox(_T("路径不存在，请检查输入的路径。"));
	}
}

void CFileManagerDlg::OnBnClickedButtonBack() {
	if (m_historyStack.size() > 1) {
		m_historyStack.pop();
		m_currentPath = m_historyStack.top();
		m_filePathEdit.SetWindowText(m_currentPath);
		m_fileListCtrl.DeleteAllItems();
		ShowFileList(m_currentPath);

		CString statusText = L"加载中";
		m_projectNum.SetWindowText(statusText);
	}
}

void CFileManagerDlg::OnBnClickedButtonParent() {
	CString parentPath = m_currentPath.Left(m_currentPath.ReverseFind(_T('\\')));
	if (!parentPath.IsEmpty()) {
		m_historyStack.push(m_currentPath);
		m_currentPath = parentPath;
		m_filePathEdit.SetWindowText(m_currentPath);
		m_fileListCtrl.DeleteAllItems();
		ShowFileList(m_currentPath);

		CString statusText = L"加载中";
		m_projectNum.SetWindowText(statusText);
	}
}

void CFileManagerDlg::OnBnClickedButtonFolder() {
	// TODO: 在此添加控件通知处理程序代码
	TCHAR szFolderPath[MAX_PATH] = { 0 };
	CString strFolderPath;
	BROWSEINFO sInfo;
	ZeroMemory(&sInfo, sizeof(BROWSEINFO));

	sInfo.pidlRoot = 0;
	sInfo.lpszTitle = _T("请选择一个文件夹：");
	sInfo.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
	sInfo.lpfn = NULL;

	// 显示文件夹选择对话框
	LPITEMIDLIST lpidlBrowse = SHBrowseForFolder(&sInfo);
	if (lpidlBrowse != NULL)
	{
		// 取得文件夹名
		if (SHGetPathFromIDList(lpidlBrowse, szFolderPath))
		{
			strFolderPath = szFolderPath;
		}
	}
	if (lpidlBrowse != NULL)
	{
		CoTaskMemFree(lpidlBrowse);
	}
	// 这里的szFolderPath就是所选择的文件夹路径
	if (szFolderPath == NULL) {
		MessageBox(_T("未选择文件夹"));
		return;
	}
	MessageBox(szFolderPath);
	m_currentPath = szFolderPath;
	m_filePathEdit.SetWindowText(m_currentPath);
	m_fileListCtrl.DeleteAllItems();
	ShowFileList(m_currentPath);
	CString statusText = L"加载中";
	m_projectNum.SetWindowText(statusText);
}



//CString CFileManagerDlg::BrowseDir(const TCHAR* szTitle, const TCHAR* pszInitPath, CWnd* pParent)
//{
//	// TODO: Add your control notification handler code here
//	CFolderPickerDialog dlg;
//
//	if (szTitle)
//	{
//		dlg.m_ofn.lpstrTitle = szTitle;
//	}
//
//	if (pszInitPath)
//	{
//		dlg.m_ofn.lpstrInitialDir = pszInitPath;
//	}
//
//	if (dlg.DoModal() != IDOK)
//	{
//		return _T("");
//	}
//
//	return dlg.GetPathName();
//}


void CFileManagerDlg::OnNMDblclkList(NMHDR* pNMHDR, LRESULT* pResult) {
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	int nItem = pNMItemActivate->iItem;
	if (nItem != -1) {
		CString path = m_curFolderFileInfo[nItem].m_filePath;
		OpenItem(path);
	}
	*pResult = 0;
}

void CFileManagerDlg::OpenItem(const CString& path) {
	if (PathIsDirectory(path)) {
		m_currentPath = path;
		m_historyStack.push(m_currentPath);
		m_fileListCtrl.DeleteAllItems();
		ShowFileList(m_currentPath);
		CString statusText = L"加载中";
		m_projectNum.SetWindowText(statusText);
		m_filePathEdit.SetWindowText(m_currentPath);
	}
	else {
		ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOWNORMAL);
	}
}

void CFileManagerDlg::OnLvnColumnclickList(NMHDR* pNMHDR, LRESULT* pResult) {
	NMLISTVIEW* pNMLV = (NMLISTVIEW*)pNMHDR;

	if (m_nSortColumn == pNMLV->iSubItem) {
		m_bSortAscending = !m_bSortAscending;
	}
	else {
		m_nSortColumn = pNMLV->iSubItem;
		m_bSortAscending = true;
	}
	m_fileListCtrl.SortItems(CompareFunc, (LPARAM)this);
	UpdateFileInfoOrder();
	*pResult = 0;
}

void CFileManagerDlg::UpdateFileInfoOrder() {
	std::vector<CFileInfo> sortedFileInfo;
	int itemCount = m_fileListCtrl.GetItemCount();
	for (int i = 0; i < itemCount; ++i) {
		int itemIndex = m_fileListCtrl.GetItemData(i);
		sortedFileInfo.push_back(m_curFolderFileInfo[itemIndex]);
	}
	m_curFolderFileInfo.clear();
	m_curFolderFileInfo = sortedFileInfo;
	m_fileListCtrl.DeleteAllItems();
	ShowFileList();
}

int CFileManagerDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) {
	CFileManagerDlg* pDlg = (CFileManagerDlg*)lParamSort;
	const CFileInfo& file1 = m_curFolderFileInfo[(int)lParam1];
	const CFileInfo& file2 = m_curFolderFileInfo[(int)lParam2];
	int result = 0;
	switch (pDlg->m_nSortColumn) {
	case 0:
		result = file1.m_fileName.CompareNoCase(file2.m_fileName);
		break;
	case 1:
		result = file1.m_fileModifyDate.Compare(file2.m_fileModifyDate);
		break;
	case 2:
		if (file1.m_bIsDir != file2.m_bIsDir) {
			result = file1.m_bIsDir ? -1 : 1;
		}
		else {
			result = file1.m_fileType.CompareNoCase(file2.m_fileType);
		}
		break;
	case 3:
		result = file1.m_fileSize - file2.m_fileSize;
		break;
	}
	return pDlg->m_bSortAscending ? result : -result;
}